---
id: dynamicmethod
title: 动态方法调用(DynamicMethod)
---

import CardLink from "@site/src/components/CardLink.js";


### 定义

命名空间：TouchSocket.Core <br/>
程序集：[TouchSocket.Core.dll](https://www.nuget.org/packages/TouchSocket.Core)

## 一、核心概念

动态方法调用模块提供高效、灵活的方法反射调用方案，支持多种底层实现方式，显著提升反射调用性能。特别针对AOT（Ahead-of-Time）编译环境优化，同时保持传统反射场景的高性能表现。

## 二、核心特性

- **多引擎支持**：
  - IL代码生成（DynamicBuilderType.IL）
  - 表达式树（DynamicBuilderType.Expression）
  - 传统反射（DynamicBuilderType.Reflect）
  - 源生成（DynamicBuilderType.SourceGenerator）
- **性能卓越**：相比原生反射调用，性能提升10倍性能
- **AOT友好**：源生成模式实现零反射，完美支持iOS/Android等AOT环境
- **智能异步支持**：自动识别Task/ValueTask返回值类型
- **全参数支持**：支持ref/out参数、泛型参数、参数默认值
- **灵活扩展**：支持自定义动态方法特性标记

## 三、快速开始

### 3.1 基本声明

```csharp showLineNumbers
public class MyClass
{
    [DynamicMethod]
    public void SimpleMethod()
    {
        Console.WriteLine("Method executed");
    }
}
```

### 3.2 基础调用

```csharp showLineNumbers
// 创建方法包装器
var method = new Method(typeof(MyClass), nameof(MyClass.SimpleMethod));

// 实例化对象
var instance = new MyClass();

// 执行方法调用
method.Invoke(instance);
```

## 四、核心功能详解

### 4.1 构建器类型选择

```csharp showLineNumbers
// 使用IL生成
var ilMethod = new Method(
    typeof(MyClass), 
    nameof(MyClass.SimpleMethod),
    DynamicBuilderType.IL
);

// 使用表达式树
var exprMethod = new Method(
    typeof(MyClass),
    nameof(MyClass.SimpleMethod),
    DynamicBuilderType.Expression
);

// 使用源生成（性能最强，AOT环境推荐）
var sourceGenMethod = new Method(
    typeof(MyClass),
    nameof(MyClass.SimpleMethod),
    DynamicBuilderType.SourceGenerator
);
```

:::tip 构建器选择建议

- **任何时候**：使用SourceGenerator，无论性能还是AOT环境，都是首选。

:::

### 4.2 异步方法支持

```csharp showLineNumbers
public class MyClass
{
    [DynamicMethod]
    public async Task<int> GetDataAsync()
    {
        await Task.Delay(100);
        return 42;
    }
}

// 异步调用
var method = new Method(typeof(MyClass), nameof(MyClass.GetDataAsync));
var result = await method.InvokeAsync(instance);
Console.WriteLine($"Result: {result}"); // 输出 42
```

### 4.3 复杂参数处理

```csharp showLineNumbers
public class MyClass
{
    [DynamicMethod]
    public void ProcessData(
        string input, 
        ref int counter,
        out string result)
    {
        counter++;
        result = $"{input}_{counter}";
    }
}

// 调用示例
var parameters = new object[] { "data", 0, null };
method.Invoke(instance, parameters);

Console.WriteLine($"Result: {parameters[2]}"); // 输出 "data_1"
```

## 五、性能优化

### 5.1 性能对比测试

:::tip 10000次调用性能分析

**核心结论**  

1. **同步方法（Add）性能**  
   - **直接调用** 最快（~2.1µs），无内存分配。  
   - **源生成器（SourceGeneratorRun）** 在 .NET 8+ 接近直接调用性能（~3.1µs），较 IL/表达式树快 6-7 倍，较反射快 28-30 倍。  
   - **反射（MethodInfo）** 性能最差（.NET 6: 400µs → .NET 8: 88µs），.NET 8+ 反射性能显著优化。  

2. **异步方法（AddAsync）性能**  
   - **直接调用** 仍最优（.NET 8: 38µs，.NET 9: 39µs）。  
   - **源生成器** 表现接近 IL/表达式树（.NET 8: 91µs vs 103µs），较反射快 2-3 倍（.NET 8: 91µs vs 184µs）。  
   - **.NET Framework 4.8.1** 异步性能最差（反射达 1,305µs），内存分配显著高于其他版本。  

3. **内存分配**  
   - 同步方法：源生成器与 IL/表达式树分配 80B，反射额外多 1B（.NET 6）。  
   - 异步方法：所有动态方法分配 ~720KB（.NET Core）或 ~802KB（Framework），反射在 Framework 分配超 1MB。  

**附：关键数据对比（.NET 8）**  

| 方法                  | 同步耗时 | 异步耗时 | 内存分配  |  
|----------------------|---------|---------|----------|  
| DirectRun            | 2.1µs   | 38µs    | 56B      |  
| SourceGeneratorRun   | 3.1µs   | 91µs    | 80B      |  
| MethodInfoRun        | 88µs    | 184µs   | 80B      |  

:::  

```csharp {7,12,18,23,29,34,40,45} showLineNumbers
| Method                       | Job                  | Runtime              | Mean         | Error     | StdDev    | Gen0     | Gen1   | Allocated |
|----------------------------- |--------------------- |--------------------- |-------------:|----------:|----------:|---------:|-------:|----------:|
| DirectRun_Add                | .NET 6.0             | .NET 6.0             |     2.132 us | 0.0031 us | 0.0027 us |        - |      - |      56 B |
| MethodILRun_Add              | .NET 6.0             | .NET 6.0             |    23.887 us | 0.0795 us | 0.0744 us |        - |      - |      80 B |
| MethodExpressionRun_Add      | .NET 6.0             | .NET 6.0             |    20.108 us | 0.1542 us | 0.1443 us |        - |      - |      80 B |
| MethodInfoRun_Add            | .NET 6.0             | .NET 6.0             |   399.999 us | 0.3781 us | 0.3537 us |        - |      - |      81 B |
| SourceGeneratorRun_Add       | .NET 6.0             | .NET 6.0             |    17.648 us | 0.0945 us | 0.0884 us |        - |      - |      80 B |
| DirectRun_AddAsync           | .NET 6.0             | .NET 6.0             |    46.567 us | 0.4623 us | 0.4098 us |  45.8984 |      - |  720080 B |
| MethodILRun_AddAsync         | .NET 6.0             | .NET 6.0             |   141.010 us | 0.8145 us | 0.7619 us |  45.8984 |      - |  720080 B |
| MethodExpressionRun_AddAsync | .NET 6.0             | .NET 6.0             |   142.758 us | 0.8197 us | 0.7266 us |  45.8984 |      - |  720080 B |
| MethodInfoRun_AddAsync       | .NET 6.0             | .NET 6.0             |   563.645 us | 1.8681 us | 1.6560 us |  45.8984 |      - |  720081 B |
| SourceGeneratorRun_AddAsync  | .NET 6.0             | .NET 6.0             |   141.399 us | 0.8781 us | 0.8214 us |  45.8984 |      - |  720080 B |
| StaticMethodRun              | .NET 6.0             | .NET 6.0             |     2.130 us | 0.0018 us | 0.0017 us |        - |      - |      56 B |
| DirectRun_Add                | .NET 8.0             | .NET 8.0             |     2.140 us | 0.0116 us | 0.0109 us |        - |      - |      56 B |
| MethodILRun_Add              | .NET 8.0             | .NET 8.0             |    19.332 us | 0.0491 us | 0.0459 us |        - |      - |      80 B |
| MethodExpressionRun_Add      | .NET 8.0             | .NET 8.0             |    12.889 us | 0.1189 us | 0.1054 us |        - |      - |      80 B |
| MethodInfoRun_Add            | .NET 8.0             | .NET 8.0             |    88.879 us | 0.1784 us | 0.1581 us |        - |      - |      80 B |
| SourceGeneratorRun_Add       | .NET 8.0             | .NET 8.0             |     3.160 us | 0.0073 us | 0.0068 us |   0.0038 |      - |      80 B |
| DirectRun_AddAsync           | .NET 8.0             | .NET 8.0             |    38.401 us | 0.1199 us | 0.1063 us |  45.8984 |      - |  720080 B |
| MethodILRun_AddAsync         | .NET 8.0             | .NET 8.0             |   103.627 us | 1.2387 us | 1.1587 us |  45.8984 |      - |  720080 B |
| MethodExpressionRun_AddAsync | .NET 8.0             | .NET 8.0             |   101.368 us | 0.7190 us | 0.6725 us |  45.8984 |      - |  720080 B |
| MethodInfoRun_AddAsync       | .NET 8.0             | .NET 8.0             |   183.882 us | 0.7238 us | 0.6044 us |  45.8984 |      - |  720080 B |
| SourceGeneratorRun_AddAsync  | .NET 8.0             | .NET 8.0             |    91.024 us | 0.6482 us | 0.6063 us |  45.8984 |      - |  720080 B |
| StaticMethodRun              | .NET 8.0             | .NET 8.0             |     2.150 us | 0.0073 us | 0.0068 us |        - |      - |      56 B |
| DirectRun_Add                | .NET 9.0             | .NET 9.0             |     2.119 us | 0.0024 us | 0.0022 us |        - |      - |      56 B |
| MethodILRun_Add              | .NET 9.0             | .NET 9.0             |    19.348 us | 0.0133 us | 0.0124 us |        - |      - |      80 B |
| MethodExpressionRun_Add      | .NET 9.0             | .NET 9.0             |    11.753 us | 0.0625 us | 0.0585 us |        - |      - |      80 B |
| MethodInfoRun_Add            | .NET 9.0             | .NET 9.0             |    91.756 us | 0.2344 us | 0.2193 us |        - |      - |      80 B |
| SourceGeneratorRun_Add       | .NET 9.0             | .NET 9.0             |     3.145 us | 0.0056 us | 0.0046 us |   0.0038 |      - |      80 B |
| DirectRun_AddAsync           | .NET 9.0             | .NET 9.0             |    39.219 us | 0.1669 us | 0.1561 us |  45.8984 |      - |  720080 B |
| MethodILRun_AddAsync         | .NET 9.0             | .NET 9.0             |   107.920 us | 0.4728 us | 0.4191 us |  45.8984 |      - |  720080 B |
| MethodExpressionRun_AddAsync | .NET 9.0             | .NET 9.0             |   106.539 us | 0.3894 us | 0.3642 us |  45.8984 |      - |  720080 B |
| MethodInfoRun_AddAsync       | .NET 9.0             | .NET 9.0             |   189.294 us | 0.7231 us | 0.6764 us |  45.8984 |      - |  720080 B |
| SourceGeneratorRun_AddAsync  | .NET 9.0             | .NET 9.0             |    99.195 us | 0.3677 us | 0.3440 us |  45.8984 |      - |  720080 B |
| StaticMethodRun              | .NET 9.0             | .NET 9.0             |     2.125 us | 0.0036 us | 0.0034 us |        - |      - |      56 B |
| DirectRun_Add                | .NET Framework 4.8.1 | .NET Framework 4.8.1 |     2.134 us | 0.0047 us | 0.0042 us |   0.0076 |      - |      56 B |
| MethodILRun_Add              | .NET Framework 4.8.1 | .NET Framework 4.8.1 |    30.162 us | 0.0629 us | 0.0588 us |        - |      - |      80 B |
| MethodExpressionRun_Add      | .NET Framework 4.8.1 | .NET Framework 4.8.1 |    56.063 us | 0.0559 us | 0.0467 us |        - |      - |      80 B |
| MethodInfoRun_Add            | .NET Framework 4.8.1 | .NET Framework 4.8.1 |   770.931 us | 5.9446 us | 5.5606 us |  50.7813 |      - |  321027 B |
| SourceGeneratorRun_Add       | .NET Framework 4.8.1 | .NET Framework 4.8.1 |    17.521 us | 0.0350 us | 0.0310 us |        - |      - |      80 B |
| DirectRun_AddAsync           | .NET Framework 4.8.1 | .NET Framework 4.8.1 |    41.866 us | 0.1300 us | 0.1216 us | 127.5024 | 0.0610 |  802442 B |
| MethodILRun_AddAsync         | .NET Framework 4.8.1 | .NET Framework 4.8.1 |   523.507 us | 2.1568 us | 1.9120 us | 126.9531 |      - |  802445 B |
| MethodExpressionRun_AddAsync | .NET Framework 4.8.1 | .NET Framework 4.8.1 |   554.333 us | 2.3657 us | 2.2129 us | 126.9531 |      - |  802445 B |
| MethodInfoRun_AddAsync       | .NET Framework 4.8.1 | .NET Framework 4.8.1 | 1,304.826 us | 1.4392 us | 1.2758 us | 177.7344 |      - | 1123389 B |
| SourceGeneratorRun_AddAsync  | .NET Framework 4.8.1 | .NET Framework 4.8.1 |   508.533 us | 0.8991 us | 0.8410 us | 126.9531 |      - |  802445 B |
| StaticMethodRun              | .NET Framework 4.8.1 | .NET Framework 4.8.1 |     3.267 us | 0.0070 us | 0.0062 us |   0.0114 |      - |      80 B |
```

<details>
<summary>基准测试代码</summary>
<div>

```csharp showLineNumbers
[SimpleJob(RuntimeMoniker.Net481)]
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net80)]
[SimpleJob(RuntimeMoniker.Net90)]
[MemoryDiagnoser]
public class BenchmarkInvokeMethodClass
{
    public BenchmarkInvokeMethodClass()
    {
        var methodInfo_Add = typeof(MyMethodClass1).GetMethod(nameof(MyMethodClass1.Add));
        var methodInfo_AddAsync = typeof(MyMethodClass1).GetMethod(nameof(MyMethodClass1.AddAsync));

        this.m_method_Add_IL = new Method(methodInfo_Add, DynamicBuilderType.IL);
        this.m_method_Add_Expression = new Method(methodInfo_Add, DynamicBuilderType.Expression);
        this.m_method_Add_SourceGenerator = new Method(methodInfo_Add, DynamicBuilderType.SourceGenerator);
        this.m_method_Add_Reflect = new Method(methodInfo_Add, DynamicBuilderType.Reflect);

        this.m_method_AddAsync_IL = new Method(methodInfo_AddAsync, DynamicBuilderType.IL);
        this.m_method_AddAsync_Expression = new Method(methodInfo_AddAsync, DynamicBuilderType.Expression);
        this.m_method_AddAsync_SourceGenerator = new Method(methodInfo_AddAsync, DynamicBuilderType.SourceGenerator);
        this.m_method_AddAsync_Reflect = new Method(methodInfo_AddAsync, DynamicBuilderType.Reflect);

        var AddStatic = typeof(MyMethodClass1).GetProperty("AddStaticAction");
    }

    private readonly Method m_method_Add_IL;
    private readonly Method m_method_Add_Expression;
    private readonly Method m_method_Add_SourceGenerator;
    private readonly Method m_method_Add_Reflect;

    private readonly Method m_method_AddAsync_IL;
    private readonly Method m_method_AddAsync_Expression;
    private readonly Method m_method_AddAsync_SourceGenerator;
    private readonly Method m_method_AddAsync_Reflect;

    public int Count=10000;

    [Benchmark]
    public void DirectRun_Add()
    {
        var myClass1 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };

        for (var i = 0; i < this.Count; i++)
        {
            myClass1.Add(a);
        }
    }

    [Benchmark]
    public void MethodILRun_Add()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            this.m_method_Add_IL.Invoke(myClass2, objects);
        }
    }

    [Benchmark]
    public void MethodExpressionRun_Add()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            this.m_method_Add_Expression.Invoke(myClass2, objects);
        }
    }

    [Benchmark]
    public void MethodInfoRun_Add()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            this.m_method_Add_Reflect.Invoke(myClass2, objects);
        }
    }

    [Benchmark]
    public void SourceGeneratorRun_Add()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            this.m_method_Add_SourceGenerator.Invoke(myClass2, objects);
        }
    }

    [Benchmark]
    public async Task DirectRun_AddAsync()
    {
        var myClass1 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };

        for (var i = 0; i < this.Count; i++)
        {
            await myClass1.AddAsync(a);
        }
    }

    [Benchmark]
    public async Task MethodILRun_AddAsync()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            await this.m_method_Add_IL.InvokeAsync(myClass2, objects);
        }
    }

    [Benchmark]
    public async Task MethodExpressionRun_AddAsync()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            await this.m_method_Add_Expression.InvokeAsync(myClass2, objects);
        }
    }

    [Benchmark]
    public async Task MethodInfoRun_AddAsync()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            await this.m_method_Add_Reflect.InvokeAsync(myClass2, objects);
        }
    }

    [Benchmark]
    public async Task SourceGeneratorRun_AddAsync()
    {
        var myClass2 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };
        for (var i = 0; i < this.Count; i++)
        {
            await this.m_method_Add_SourceGenerator.InvokeAsync(myClass2, objects);
        }
    }

    [Benchmark]
    public void StaticMethodRun()
    {
        var myClass1 = new MyMethodClass1();

        var a = new object();

        var objects = new object[] { a };

        for (var i = 0; i < this.Count; i++)
        {
            MyMethodClass1.AddStatic(myClass1, objects);
        }
    }
}


public class MyMethodClass1
{
    public static object AddStatic(object myClass, object[] ps)
    {
        var a = ps[0];
        var result = ((MyMethodClass1)myClass).Add(a);
        return result;
    }

    //这个是被调用函数。
    [DynamicMethod]
    public object Add(object obj)
    {
        return obj;
    }
    [DynamicMethod]
    public Task<object> AddAsync(object obj)
    {
        return Task.FromResult(obj);
    }
}
```

</div>
</details>


### 5.2 缓存策略

```csharp showLineNumbers
// 推荐在应用初始化时预加载方法
public static class MethodCache
{
    public static readonly Method ProcessMethod = new Method(
        typeof(MyClass),
        nameof(MyClass.ProcessData),
        DynamicBuilderType.IL
    );
}

// 后续重复使用缓存实例
MethodCache.ProcessMethod.Invoke(instance);
```

## 六、高级用法

### 6.1 自定义特性标记

```csharp showLineNumbers
// 定义自定义特性
[AttributeUsage(AttributeTargets.Method)]
public class MyDynamicAttribute : DynamicMethodAttribute {}

// 标记方法
public class CustomService
{
    [MyDynamic]
    public void CustomOperation() { }
}

// 获取自定义标记方法
var methods = typeof(CustomService)
    .GetMethods()
    .Where(m => m.IsDefined(typeof(MyDynamicAttribute)));
```

## 七、示例项目

<CardLink link="https://gitee.com/RRQM_Home/TouchSocket/tree/master/examples/Core/AotDynamicMethodConsoleApp"/>
